package com.xbongbong.workflow.service.strategy.data.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.TaskTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.pojo.dto.SaasFormSaveDTO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.paas.util.FormDataUtil;
import com.xbongbong.pro.constant.BusinessConstant;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.fund.enums.ModelTypeEnum;
import com.xbongbong.pro.formdata.pojo.SaasNeedRedundantAttrPojo;
import com.xbongbong.pro.message.constant.OutstockPushConstant;
import com.xbongbong.pro.message.enums.PushTypeEnum;
import com.xbongbong.pro.message.pojo.PushRefTypePojo;
import com.xbongbong.pro.message.pojo.dto.ConsistencySyncRabbitMqDTO;
import com.xbongbong.pro.message.pojo.dto.MessageRabbitMqDTO;
import com.xbongbong.pro.message.service.MessageService;
import com.xbongbong.pro.product.pojo.dto.CostRecalculationDTO;
import com.xbongbong.pro.user.pojo.ReturnUserAndDepartmentPojo;
import com.xbongbong.pro.workflow.enums.WorkflowOperateEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.ContractProductEntity;
import com.xbongbong.saas.domain.entity.OutstockProductEntity;
import com.xbongbong.saas.domain.entity.ProductStockUpdateEntity;
import com.xbongbong.saas.domain.entity.PurchaseBalanceEntity;
import com.xbongbong.saas.domain.entity.SmartReplenishmentEntity;
import com.xbongbong.saas.domain.entity.ext.ContractEntityExt;
import com.xbongbong.saas.domain.entity.ext.OutstockEntityExt;
import com.xbongbong.saas.enums.OutstockTypeEnum;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.StockTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.enums.business.ContractOutstockEnum;
import com.xbongbong.saas.enums.business.OutstockEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.help.ReceivablesHelper;
import com.xbongbong.saas.help.workflow.ContractHelp;
import com.xbongbong.saas.help.workflow.OutstockHelp;
import com.xbongbong.saas.help.workflow.ProductSerialHelp;
import com.xbongbong.saas.help.workflow.WorkflowProductHelp;
import com.xbongbong.saas.model.ContractModel;
import com.xbongbong.saas.model.ContractProductModel;
import com.xbongbong.saas.model.CustomerUserModel;
import com.xbongbong.saas.model.FundSetModel;
import com.xbongbong.saas.model.OutstockModel;
import com.xbongbong.saas.model.OutstockProductModel;
import com.xbongbong.saas.model.PaasFormSubDataModel;
import com.xbongbong.saas.model.PurchaseBalanceModel;
import com.xbongbong.saas.model.SmartReplenishmentModel;
import com.xbongbong.saas.service.ConsistencySyncService;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.UserModel;
import com.xbongbong.workflow.domain.entity.WorkflowBackupDataEntity;
import com.xbongbong.workflow.model.WorkflowBackupDataModel;
import com.xbongbong.workflow.pojo.Data;
import com.xbongbong.workflow.pojo.User;
import com.xbongbong.workflow.pojo.WorkflowTransferPOJO;
import com.xbongbong.workflow.pojo.dto.WorkflowReceivablesDTO;
import com.xbongbong.workflow.service.strategy.data.AbstractWorkflowDataStrategy;
import com.xbongbong.workflow.service.strategy.data.WorkflowDataProcessStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 *
 * @author 魏荣杰
 *
 */
@Service
@Slf4j
public class WorkflowOutstockStrategy extends AbstractWorkflowDataStrategy implements WorkflowDataProcessStrategy {

    @Resource
    private ContractModel contractModel;
    @Resource
    private CustomerUserModel customerUserModel;
    @Resource
    private UserModel userModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private WorkflowBackupDataModel workflowBackupDataModel;
    @Resource
    private ProductSerialHelp productSerialHelp;
    @Resource
    private OutstockHelp outstockHelp;
    @Resource
    private OutstockModel outstockModel;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private FundSetModel fundSetModel;
    @Resource
    private ReceivablesHelper receivablesHelper;
    @Resource
    private MessageService messageService;
    @Resource
    private OutstockProductModel outstockProductModel;
    @Resource
    private WorkflowProductHelp workflowProductHelp;
    @Resource
    private PaasFormSubDataModel paasFormSubDataModel;
    @Resource
    private PurchaseBalanceModel purchaseBalanceModel;
    @Resource
    private SmartReplenishmentModel smartReplenishmentModel;
    @Resource
    private ContractProductModel contractProductModel;
    @Resource
    private ContractHelp contractHelp;
    @Resource
    private ConsistencySyncService consistencySyncService;


    @Override
    public List<Integer> type() {
        return Arrays.asList(XbbRefTypeEnum.OUTSTOCK.getCode(), XbbRefTypeEnum.CONTRACT_OUTSTOCK.getCode(), XbbRefTypeEnum.OTHER_OUTSTOCK.getCode(), XbbRefTypeEnum.RETURNED_PURCHASE_OUTSTOCK.getCode(), XbbRefTypeEnum.WORK_ORDER_OUTSTOCK.getCode(), XbbRefTypeEnum.PRODUCTION_MATERIEL_OUTSTOCK.getCode());
    }

    @Override
    public void save(WorkflowTransferPOJO workflowTransferPOJO, SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo) throws XbbException {
        // 文件柜
        saveDataCabinetFile(workflowTransferPOJO);


        String corpid = workflowTransferPOJO.getCorpid();
        Data pojoData = workflowTransferPOJO.getData();
        Long formId = pojoData.getFormId();
        PaasFormEntity paasFormEntity = paasFormModel.getByKey(formId, corpid);
        Long dataId = pojoData.getId();
        JSONObject data = pojoData.getData();
        User user = workflowTransferPOJO.getUser();

        Integer type = data.getInteger(OutstockEnum.TYPE.getAttr());
        Long refId = Objects.isNull(data.getLong(OutstockEnum.REF_ID.getAttr())) ? 0L : data.getLong(OutstockEnum.REF_ID.getAttr());
        // 改为新建时进行以下逻辑：产品保存、库存更新、上游单据更新
        // 获取对应数据
        // 获取关联产品的数据
        JSONArray productJsonArray = data.getJSONArray(OutstockEnum.PRODUCT.getAttr());

        // 更新出库单产品的分仓库存、批次库存
        Map<String, Object> param = new HashMap<>();
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        param.put("refId", refId);
        param.put("type", type);
        param.put("outWarehouseId", dataId);
        List<OutstockProductEntity> outstockProductModelEntitys = outstockProductModel.findEntitys(param);
        Map<Long, ProductStockUpdateEntity> productAddMap = outstockHelp.addUpdateStock(outstockProductModelEntitys, corpid);
        workflowProductHelp.updateProductStock(productAddMap, corpid);
        Map<Long,Long> productIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (OutstockProductEntity outstockProductEntity:outstockProductModelEntitys){
            productIdMap.put(outstockProductEntity.getProductId(),outstockProductEntity.getParentId());
        }
        Map<Long, JSONObject> productMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (!productJsonArray.isEmpty()){
            for (int i = 0; i < productJsonArray.size(); i++) {
                JSONObject productObject = productJsonArray.getJSONObject(i);
                Long productId = productObject.getLong(SelectProductEnum.PRODUCT.getAttr());
                productObject.put(ProductEnum.PARENT_ID.getSaasAttr(),productIdMap.get(productId));
                productMap.put(productObject.getLong(BusinessConstant.PRODUCT_SUB_ID), productObject);
            }
        }
        data.put(OutstockEnum.PRODUCT.getAttr(),productJsonArray);
        // 完成工作流，将序列号插入到序列号流水表，并且更新结存表
        productSerialHelp.saveSerial(corpid, pojoData.getBusinessType(), data, dataId, data.getString(BasicConstant.SERIAL_NO), productMap);
        // 更新上游单据
        OutstockEntityExt outstockEntityExt = outstockModel.getByKey(dataId, corpid);
        outstockEntityExt.setData(data);

        outstockHelp.setOutstockDocumentsNew(corpid, data, paasFormEntity.getDistributorMark(),  outstockEntityExt);
        //发送重算消息
        CostRecalculationDTO costRecalculationDTO = new CostRecalculationDTO();
        SaasFormSaveDTO saasFormSaveDTOCost = new SaasFormSaveDTO();
        saasFormSaveDTOCost.setCorpid(corpid);
        saasFormSaveDTOCost.setBusinessType(pojoData.getBusinessType());
        saasFormSaveDTOCost.setNewData(data);
        saasFormSaveDTOCost.setNewPaasFormDataEntity(outstockEntityExt);
        costRecalculationDTO.setType(StockTypeEnum.OUT_STOCK.getCode());
        costRecalculationDTO.setData(data);
        costRecalculationDTO.setStockId(dataId);
        costRecalculationDTO.setCorpid(corpid);
        costRecalculationDTO.setMark(BasicConstant.ONE);
        costRecalculationDTO.setIsWorkFlow(BasicConstant.ZERO);
        costRecalculationDTO.setSaasFormSaveDTO(saasFormSaveDTOCost);
        //将流水放至重算方法中生成，保证处理的先后顺序
        /*stockFlowBillHelp.caculateStockModification4Save(corpid, pojoData.getBusinessType(), data, outstockEntityExt);
        batchFlowBillHelp.batchFlowModification4Save(corpid, pojoData.getSubBusinessType(), data, outstockEntityExt);*/
        receivablesHelper.costRecalculationWorkFlow(costRecalculationDTO);

        if (Objects.equals(type, OutstockTypeEnum.CONTRACT_OUTSTOCK.getCode())) {
            // TODO: 2021/8/23
            //获取当前处于什么模式
            Long modelType = fundSetModel.getModelType(corpid,XbbRefTypeEnum.CRM);
            if(Objects.equals(modelType, ModelTypeEnum.OUTSTOCK.getCode())){
                UserEntity userEntity = userModel.getByKey(user.getUserId(), corpid);
                UserVO userVO = new UserVO();
                BeanUtil.copyProperties(userEntity, userVO);


                SaasFormSaveDTO saasFormSaveDTO = new SaasFormSaveDTO();
                saasFormSaveDTO.setCorpid(corpid);
                saasFormSaveDTO.setAmountDetail(saasNeedRedundantAttrPojo.getAmountDetail());
                saasFormSaveDTO.setNewPaasFormDataEntity(outstockEntityExt);
                saasFormSaveDTO.setBusinessType(pojoData.getBusinessType());

                List<ReturnUserAndDepartmentPojo> ownList = new ArrayList<>();
                ownList.add(new ReturnUserAndDepartmentPojo(data.getString(FieldTypeEnum.OWNERID.getAlias())));
                List<ReturnUserAndDepartmentPojo> coUserList = new ArrayList<>();
                coUserList.add(new ReturnUserAndDepartmentPojo(data.getString(FieldTypeEnum.COUSERID.getAlias())));

                saasFormSaveDTO.setOwnerId(ownList);
                saasFormSaveDTO.setCoUserId(coUserList);
                saasFormSaveDTO.setProcessCreatorId(user.getUserId());
                saasFormSaveDTO.setIsImport(workflowTransferPOJO.getIsImport());
                saasFormSaveDTO.setLoginUser(userVO);

                WorkflowReceivablesDTO workflowReceivablesDTO = new WorkflowReceivablesDTO();
                workflowReceivablesDTO.setSaasFormSaveDTO(saasFormSaveDTO);
                workflowReceivablesDTO.setModelType(modelType);

                receivablesHelper.createReceivablesHandle(saasFormSaveDTO, modelType, null);
//                receivablesHelper.createReceivablesHandle(saasFormSaveDTO, modelType, null);
            }

            // 销售出库消息推送
            try {
                ContractEntityExt contractFormDataEntity = contractModel.getByKey(refId, corpid);
                if (Objects.nonNull(contractFormDataEntity)) {
                    Long customerId = contractFormDataEntity.getData().getLong(ContractEnum.LINK_CUSTOMER.getAttr());
                    //客户负责人
                    List<String> customerUserList = customerUserModel.getCustomerUserIdList(corpid, Collections.singletonList(customerId), null);
                    if (customerUserList == null) {
                        customerUserList = new ArrayList<>();
                    }
                    //合同创建人
                    customerUserList.add(contractFormDataEntity.getCreatorId());
                    //推送给仓库主管
                    List<UserEntity> managers = userModel.getUsersByRoleId(corpid, Collections.singletonList(22));
                    for (UserEntity manager : managers) {
                        customerUserList.add(manager.getUserId());
                    }
                    PushRefTypePojo.Options options = new PushRefTypePojo.Options(contractFormDataEntity.getAppId(), contractFormDataEntity.getMenuId(), contractFormDataEntity.getFormId(), refId, Collections.singletonList(refId), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.CONTRACT.getCode(), XbbRefTypeEnum.CONTRACT.getCode());
                    MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, customerUserList, Collections.singletonList(refId), 0, null, I18nMessageUtil.getMessage(OutstockPushConstant.OUTSTOCK_TITLE), String.format(I18nMessageUtil.getMessage(OutstockPushConstant.CONTRACT_OUTSTOCK_CONTENT), contractFormDataEntity.getSerialNo()), null, options);
                    messageService.delayPushDingtalkOAMessage(messageRabbitMqDTO, PushTypeEnum.OUTSTOCK_SUCCESS_PUSH);
                }

                updateContractAmount(data, contractFormDataEntity);

                contractModel.update(contractFormDataEntity);

            } catch (Exception e) {
                log.error("销售出库消息推送", e);
            }
        }

        // api
        apiHook(workflowTransferPOJO);
        addLinkDataDynamic(workflowTransferPOJO);
        // log
        afterSaveLog(workflowTransferPOJO);
    }

    @Override
    public void update(WorkflowTransferPOJO workflowTransferPOJO, SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo) throws XbbException {
        // 文件柜
        saveDataCabinetFile(workflowTransferPOJO);

        String corpid = workflowTransferPOJO.getCorpid();
        Data pojoData = workflowTransferPOJO.getData();
        JSONObject data = pojoData.getData();
        Long formId = pojoData.getFormId();

        Integer type = data.getInteger(OutstockEnum.TYPE.getAttr());

        if (Objects.equals(type,OutstockTypeEnum.CONTRACT_OUTSTOCK.getCode())) {
            PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
            Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(paasFormExplainEntity.getExplains());
            FieldAttrEntity nameFieldAttrEntity = explainMap.get(ContractOutstockEnum.EXPRESS_NAME.getAttr());
            FieldAttrEntity noFieldAttrEntity = explainMap.get(ContractOutstockEnum.EXPRESS_NO.getAttr());

            WorkflowBackupDataEntity workflowBackupDataEntity = workflowBackupDataModel.getByKey(workflowTransferPOJO.getBackupDataId(), corpid);
            JSONObject oldData = workflowBackupDataEntity.getData();

            boolean updateExpressName = Objects.nonNull(nameFieldAttrEntity) && !Objects.equals(oldData.getString(OutstockEnum.EXPRESS_NAME.getAttr()), data.get(OutstockEnum.EXPRESS_NAME.getAttr()));
            boolean updateExpressNo = Objects.nonNull(noFieldAttrEntity) && !Objects.equals(oldData.getString(OutstockEnum.EXPRESS_NO.getAttr()), data.get(OutstockEnum.EXPRESS_NO.getAttr()));
            Long contractId = data.getLong(OutstockEnum.REF_ID.getAttr());
            ContractEntityExt contractEntityExt = contractModel.getByKey(contractId,corpid);
            if (updateExpressName || updateExpressNo) {
                if (updateExpressName) {
                    contractEntityExt.getData().put(ContractEnum.EXPRESS_NAME.getAttr(), data.get(OutstockEnum.EXPRESS_NAME.getAttr()));
                }
                if (updateExpressNo) {
                    contractEntityExt.getData().put(ContractEnum.EXPRESS_NO.getAttr(), data.get(OutstockEnum.EXPRESS_NO.getAttr()));
                }
//                contractModel.update(contractEntityExt);
            }

            updateContractAmount(data, contractEntityExt);
            // 更新合同数据
            contractModel.update(contractEntityExt);
            //一致性同步，销售出库单产生应收，那么一旦销售出库单编号改了之后，那么下游应收款来源单据中的编号应该同步修改
            try {
                String oldOutStockSeriNo = workflowBackupDataEntity.getData().getString(BasicConstant.SERIAL_NO);
                String newOutStockSeriNo = data.getString(BasicConstant.SERIAL_NO);
                if (!Objects.equals(oldOutStockSeriNo, newOutStockSeriNo)) {
                    ConsistencySyncRabbitMqDTO consistencySyncRabbitMqDTO = new ConsistencySyncRabbitMqDTO(corpid, pojoData.getId(), newOutStockSeriNo);
                    consistencySyncService.syncContractOutStock(consistencySyncRabbitMqDTO);
                }
            }catch (Exception e){
                log.error("数据一致性同步", e);
            }
        }

        // api
        apiHook(workflowTransferPOJO);
        // log
        afterUpdateLog(workflowTransferPOJO);
    }

    private void updateContractAmount(JSONObject data, ContractEntityExt contractEntityExt) {
        JSONObject contractEntityExtData = contractEntityExt.getData();
        // 修改的新数据
        // 合同数据必须存在已以出库优惠金额并且销售出库单存在优惠金额
        String outstockDiscountAmountAttr = ContractEnum.OUTSTOCK_DISCOUNT_AMOUNT.getAttr();
        String discountAmount = ContractOutstockEnum.DISCOUNT_AMOUNT.getAttr();
        if(contractEntityExtData.containsKey(outstockDiscountAmountAttr) && data.containsKey(discountAmount)){
            // 以出库优惠金额 += 销售出库单存在优惠金额
            BigDecimal outstockDiscountAmount = contractEntityExtData.getBigDecimal(outstockDiscountAmountAttr).add(data.getBigDecimal(discountAmount));
            // 跟新合同以出库优惠金额
            contractEntityExtData.put(ContractEnum.OUTSTOCK_DISCOUNT_AMOUNT.getAttr(), outstockDiscountAmount);
        }
        // 合同数据必须存在已以出库其他费用并且销售出库单存在其他费用
        String outstockOtherExpenseAttr = ContractEnum.OUTSTOCK_OTHER_EXPENSE.getAttr();
        String otherExpense = ContractOutstockEnum.OTHER_EXPENSE.getAttr();
        if(contractEntityExtData.containsKey(outstockOtherExpenseAttr) && data.containsKey(otherExpense)){
            // 以出库优惠金额 += 销售出库单存在优惠金额
            BigDecimal outstockDiscountAmount = contractEntityExtData.getBigDecimal(outstockOtherExpenseAttr).add(data.getBigDecimal(otherExpense));
            // 跟新合同以出库优惠金额
            contractEntityExtData.put(outstockOtherExpenseAttr, outstockDiscountAmount);
        }
    }

    @Override
    public void updateBack(Long taskId, WorkflowTransferPOJO workflowTransferPOJO) throws XbbException {
        try {
            String corpid = workflowTransferPOJO.getCorpid();
            Long backupDataId = workflowTransferPOJO.getBackupDataId();
            Long dataId = workflowTransferPOJO.getData().getId();
            WorkflowBackupDataEntity workflowBackupDataEntity = workflowBackupDataModel.getByKey(backupDataId, corpid);
            if (Objects.nonNull(workflowBackupDataEntity)) {
                JSONObject data = workflowBackupDataEntity.getData();

                replenishAttrForBackupData(workflowTransferPOJO.getData().getData(), data);

                OutstockEntityExt outstockEntityExt = new OutstockEntityExt();
                outstockEntityExt.setId(dataId);
                outstockEntityExt.setCorpid(corpid);
                outstockEntityExt.setData(data);
                outstockEntityExt.setSerialNo(data.getString(FieldTypeEnum.SERIALNO.getAlias()));
                // 获取负责人
                outstockEntityExt.setOwnerId(getOwnerId(data));
                outstockEntityExt.setDepartmentId(data.getLong(FieldTypeEnum.DEPARTMENTID.getAlias()));

                FormDataUtil.removeSystemData(data);
                data.remove(StringConstant.PRODUCT);
                if (Objects.equals(workflowTransferPOJO.getOperate(), WorkflowOperateEnum.UPDATE.getType())) {
                    outstockEntityExt.setFlowStatus(FlowStatusEnum.PASS.getType());
                }
                outstockModel.update(outstockEntityExt);
                // 回退被删掉的子表单
                updateBackSubForm(outstockEntityExt, corpid, IndexTypeEnum.IDX_SAAS_OUTSTOCK_SUB);
                //回退被删掉的富文本
                updateBackRichText(taskId, workflowTransferPOJO);
                // 还原合同中的快递单号和快递公司
                Integer type = data.getInteger(OutstockEnum.TYPE.getAttr());
                if (Objects.equals(type,OutstockTypeEnum.CONTRACT_OUTSTOCK.getCode())){
                    PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(workflowTransferPOJO.getData().getFormId(), corpid);
                    Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(paasFormExplainEntity.getExplains(), null);
                    FieldAttrEntity nameFieldAttrEntity = explainMap.get(ContractOutstockEnum.EXPRESS_NAME.getAttr());
                    FieldAttrEntity noFieldAttrEntity = explainMap.get(ContractOutstockEnum.EXPRESS_NO.getAttr());
                    boolean updateExpressName = Objects.nonNull(nameFieldAttrEntity) ;
                    boolean updateExpressNo = Objects.nonNull(noFieldAttrEntity);
                    if (updateExpressName || updateExpressNo) {
                        Long contractId = data.getLong(OutstockEnum.REF_ID.getAttr());
                        ContractEntityExt contractEntityExt = contractModel.getByKey(contractId,corpid);
                        if (Objects.nonNull(contractEntityExt)) {
                            JSONObject updateData = new JSONObject();
                            if (updateExpressName) {
                                updateData.put(ContractEnum.EXPRESS_NAME.getAttr(), data.get(OutstockEnum.EXPRESS_NAME.getAttr()));
                            }
                            if (updateExpressNo) {
                                updateData.put(ContractEnum.EXPRESS_NO.getAttr(), data.get(OutstockEnum.EXPRESS_NO.getAttr()));
                            }
                            UpdateDataEntity updateDataEntity = ExplainUtil.getUpdateData(contractId, updateData, corpid);
                            contractModel.updateBatch(Collections.singletonList(updateDataEntity), corpid);
                        }
                    }

                }

            }
        } catch (Exception e) {
            log.error("com.xbongbong.workflow.service.strategy.data.impl.WorkflowOutstockStrategy.updateBack error ", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    @Override
    public void approvalFailed(Long taskId, WorkflowTransferPOJO workflowTransferPOJO, Integer taskType) throws XbbException {
        try {
            String corpid = workflowTransferPOJO.getCorpid();
            Data workflowData = workflowTransferPOJO.getData();
            Long dataId = workflowData.getId();
            Long formId = workflowData.getFormId();
            Integer businessType = workflowData.getBusinessType();
            Integer saasMark = workflowData.getSaasMark();
            OutstockEntityExt outstockEntityExt = new OutstockEntityExt();
            outstockEntityExt.setId(dataId);
            if (Objects.equals(TaskTypeEnum.REVOKE.getType(), taskType)) {
                outstockEntityExt.setFlowStatus(FlowStatusEnum.REVOKE.getType());
            } else {
                outstockEntityExt.setFlowStatus(FlowStatusEnum.REJECT.getType());
            }
            outstockEntityExt.setCorpid(corpid);
            outstockEntityExt.setUpdateTime(DateTimeUtil.getInt());
            outstockModel.update(outstockEntityExt);
            // 子表单
            DelEnum del = DelEnum.APPROVE_FAILED;

            paasFormSubDataModel.deleteBatchByDataId(Collections.singletonList(dataId), corpid, IndexTypeEnum.IDX_SAAS_OUTSTOCK_SUB, del);
            //富文本
            deleteFormRichText(dataId, corpid, formId, businessType, saasMark, DelEnum.NORMAL);

            // 关联产品
            List<OutstockProductEntity> productList = outstockProductModel.getProductsByOutstockIdIn(corpid, Arrays.asList(dataId));
            if (CollectionsUtil.isNotEmpty(productList)) {
                List<Long> idIn = new ArrayList<>();
                productList.forEach(item->idIn.add(item.getId()));
                outstockProductModel.deleteBatchById(idIn, corpid, del.getDel());
                // 拒绝销售出库单回退采购结存及智能补货数据
                if (Objects.equals(XbbRefTypeEnum.CONTRACT_OUTSTOCK.getCode(),businessType)){
                    rollBackSmartData(corpid,productList);
                }
            }
        } catch (Exception e) {
            log.error("com.xbongbong.workflow.service.strategy.data.impl.WorkflowOutstockStrategy.approvalFailed error ", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    private void rollBackSmartData(String corpid,List<OutstockProductEntity> productList) throws XbbException{
        Map<String,Double> balanceMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<String> onlyKeyList = new ArrayList<>();
        // key=productId  value=删除的产品总量
        Map<Long,Double> productMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<Long> productIdList = new ArrayList<>();
        List<Long> contractProductIdList = new ArrayList<>();
        Set<Long> contractIdSet = new HashSet<>();
        for (OutstockProductEntity outstockProductEntity : productList) {
            Long productId = outstockProductEntity.getProductId();
            Double productNum = outstockProductEntity.getProductNum();
            Long contractProductId = outstockProductEntity.getRefProductId();
            Long contractId = outstockProductEntity.getRefId();
            contractProductIdList.add(contractProductId);
            contractIdSet.add(contractId);
            if (productMap.containsKey(productId)){
                productMap.put(productId, Arith.add(productMap.get(productId),productNum));
            }else {
                productMap.put(productId,productNum);
                productIdList.add(productId);
            }
            // 封装删除的同一个合同下的某一个产品总量
            String onlyKey = outstockProductEntity.getRefProductId() + "_" + outstockProductEntity.getProductId();
            if(!balanceMap.containsKey(onlyKey)){
                onlyKeyList.add(onlyKey);
                balanceMap.put(onlyKey,outstockProductEntity.getProductNum());
            }else {
                balanceMap.put(onlyKey,Arith.add(balanceMap.get(onlyKey),outstockProductEntity.getProductNum()));
            }
        }
        // 根据onlyKeyList查询出所有结存数据
        List<PurchaseBalanceEntity> purchaseBalanceEntityList = purchaseBalanceModel.findByOnlyKeys(corpid, onlyKeyList);
        // 封装结存的超发库存以及结存方案已与产品确认 先回退超发的 多余的再回退到结余
        if(CollectionsUtil.isNotEmpty(purchaseBalanceEntityList)){
            for (PurchaseBalanceEntity purchaseBalanceEntity : purchaseBalanceEntityList) {
                String onlyKey = purchaseBalanceEntity.getOnlyKey();
                if (balanceMap.containsKey(onlyKey)){
                    Double balanceNum = purchaseBalanceEntity.getBalanceNum();
                    Double exceedStockNum = purchaseBalanceEntity.getExceedStockNum();
                    Double delProductNum = balanceMap.get(onlyKey);
                    // 删除数量 如果大于超发的 则超发库存全部回退 多余的回到结存 小于的话全部回退到超发库存
                    purchaseBalanceEntity.setExceedStockNum(delProductNum >= exceedStockNum ? 0D : Arith.sub(exceedStockNum,delProductNum));
                    // 删除的数量如果大于超发 则结存数量为之前的加上删除的大于超发的那部分  如果小于超发 则全部回退到超发 结存不变
                    purchaseBalanceEntity.setBalanceNum(delProductNum >= exceedStockNum ? Arith.add(purchaseBalanceEntity.getBalanceNum(),Arith.sub(delProductNum,exceedStockNum)): purchaseBalanceEntity.getBalanceNum());
                }
            }
            try {
                purchaseBalanceModel.updateBatch(purchaseBalanceEntityList,corpid);
            }catch (Exception e){
                log.error("com.xbongbong.workflow.service.strategy.data.impl.WorkflowOutstockStrategy.updateBack error 更新采购结存表数据时出错", e);
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
        }
        // 查询出删除的销售出库单关联的所有产品的智能补货数据
        List<SmartReplenishmentEntity> smartReplenishmentEntityList = smartReplenishmentModel.getByProductList(corpid,productIdList);
        if (CollectionsUtil.isNotEmpty(smartReplenishmentEntityList)){
            for (SmartReplenishmentEntity smartReplenishmentEntity : smartReplenishmentEntityList) {
                Long smartProductId = smartReplenishmentEntity.getProductId();
                if (productMap.containsKey(smartProductId)){
                    smartReplenishmentEntity.setWaitOutstockNum(Arith.add(smartReplenishmentEntity.getWaitOutstockNum(),productMap.get(smartProductId)));
                }
            }
            try {
                smartReplenishmentModel.updateBatch(smartReplenishmentEntityList,corpid);
            }catch (Exception e){
                log.error("com.xbongbong.workflow.service.strategy.data.impl.WorkflowOutstockStrategy.updateBack error 更新智能补货表数据时出错", e);
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
        }
        // 处理合同产品表中缺货数量字段
        if(CollectionsUtil.isNotEmpty(contractProductIdList)){
            List<ContractProductEntity> contractProductEntityList = contractProductModel.getById(contractProductIdList, corpid);
            if (CollectionsUtil.isNotEmpty(contractProductEntityList)) {
                contractHelp.handleWaitPurchaseNum(corpid, contractProductEntityList, contractIdSet);
                try {
                    contractProductModel.updateBatch(contractProductEntityList, corpid);
                } catch (Exception e) {
                    log.error("WorkflowPurchaseStrategy.addRollBackSmartData 更新合同产品表中缺货数量时出错", e);
                }
            }
        }
    }

}
